﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace CatEars.Core.Collections
{
    /// <summary>
    /// 扩展方便使用的Dictionary
    /// </summary>
    /// <typeparam name="TKey">key类型</typeparam>
    /// <typeparam name="TValue">value类型</typeparam>
    [DebuggerDisplay("Count={InnerDict.Count}")]
    public class DictEx<TKey, TValue> : IDictionary<TKey, TValue>
    {
        /// <summary>
        /// 内部字典
        /// </summary>
        public virtual IDictionary<TKey, TValue> InnerDict { get; protected set; }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public DictEx()
            : this(null)
        {
        }

        /// <summary>
        /// 重载构造函数
        /// </summary>
        /// <param name="dict"></param>
        public DictEx(IDictionary<TKey, TValue> dict)
        {
            if (dict == null)
            {
                InnerDict = new Dictionary<TKey, TValue>();
            }
            else
            {
                InnerDict = dict;
            }
        }

        /// <summary>
        /// 获取或设置值
        /// </summary>
        /// <param name="key">key【NotNull】</param>
        /// <returns>value</returns>
        public TValue this[TKey key]
        {
            get { return GetOrDefault(key); }
            set { InnerDict[key] = value; }
        }

        /// <summary>
        /// 通过key获取对象 或者用 invoke 创建一个新对象的并添加到字典中
        /// </summary>
        /// <param name="key">搜索key【NotNull】</param>
        /// <param name="invoke">创建一个新的对象 委托【NotNull】</param>
        /// <returns>对象</returns>
        public TValue GetOrAddValue(TKey key, Func<TValue> invoke)
        {
            return ExIDictionary.GetOrAddValue(InnerDict, key, invoke);
        }

        /// <summary>
        /// 通过key获取对象 或者用 invoke 创建一个新对象的并添加到字典中
        /// </summary>
        /// <param name="key">搜索key【NotNull】</param>
        /// <param name="invoke">创建一个新的对象 委托【NotNull】</param>
        /// <param name="objs">创建一个新对象 参数【数量与invoke输入参数对应】</param>
        /// <returns>对象</returns>
        public TValue GetOrAddValue(TKey key,
            Func<object[], TValue> invoke,
            params object[] objs)
        {
            return ExIDictionary.GetOrAddValue(InnerDict, key, invoke, objs);
        }

        /// <summary>
        /// 从字典中获取对象 找不到则返回default
        /// </summary>
        /// <param name="key">搜索key【NotNull】</param>
        /// <returns>对象</returns>
        public TValue GetOrDefault(TKey key)
        {
            return ExIDictionary.GetOrDefault(InnerDict, key);
        }

        /// <summary>
        /// 从字典中获取对象 找不到则返回default
        /// </summary>
        /// <param name="key">搜索key【NotNull】</param>
        /// <param name="defaultValue">搜索不到时的默认值</param>
        /// <returns>对象</returns>
        public TValue GetOrDefault(TKey key, TValue defaultValue)
        {
            return ExIDictionary.GetOrDefault(InnerDict, key, defaultValue);
        }

        /// <summary>
        /// 添加对象 存在则忽略
        /// </summary>
        /// <param name="key">搜索key【NotNull】</param>
        /// <param name="value">要插入的值</param>
        /// <returns>是否成功</returns>
        public bool AddIfNotExist(TKey key, TValue value)
        {
            return ExIDictionary.AddIfNotExist(InnerDict, key, value);
        }

        /// <summary>
        /// 添加对象 存在则替换
        /// </summary>
        /// <param name="key">搜索key【NotNull】</param>
        /// <param name="value">要插入的值</param>
        /// <returns>是否替换</returns>
        public bool AddOrReplace(TKey key, TValue value)
        {
            return ExIDictionary.AddOrReplace(InnerDict, key, value);
        }

        #region IDictionary<TKey, TValue>实现

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key">【NotNull】</param>
        /// <param name="value"></param>
        public void Add(TKey key, TValue value)
        {
            InnerDict.Add(key, value);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key">【NotNull】</param>
        /// <returns></returns>
        public bool ContainsKey(TKey key)
        {
            return InnerDict.ContainsKey(key);
        }

        /// <summary>
        /// 
        /// </summary>
        public ICollection<TKey> Keys { get { return InnerDict.Keys; } }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key">【NotNull】</param>
        /// <returns></returns>
        public bool Remove(TKey key)
        {
            return InnerDict.Remove(key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key">【NotNull】</param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            return InnerDict.TryGetValue(key, out value);
        }

        /// <summary>
        /// 
        /// </summary>
        public ICollection<TValue> Values { get { return InnerDict.Values; } }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item">【NotNull】</param>
        public void Add(KeyValuePair<TKey, TValue> item)
        {
            InnerDict.Add(item);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            InnerDict.Clear();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item">【NotNull】</param>
        /// <returns></returns>
        public bool Contains(KeyValuePair<TKey, TValue> item)
        {
            return InnerDict.Contains(item);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="array">【NotNull】</param>
        /// <param name="arrayIndex"></param>
        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            InnerDict.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// 
        /// </summary>
        public int Count { get { return InnerDict.Count; } }

        /// <summary>
        /// 
        /// </summary>
        public bool IsReadOnly { get { return InnerDict.IsReadOnly; } }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item">【NotNull】</param>
        /// <returns></returns>
        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            return InnerDict.Remove(item);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return InnerDict.GetEnumerator();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)InnerDict).GetEnumerator();
        }

        #endregion
    }
}
